package com.deng.api.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.deng.api.entity.AuthUser;
import com.deng.api.entity.SysUser;
import com.deng.api.jwt.JWTConfig;
import com.deng.api.jwt.JwtTokenUtil;
import com.deng.api.service.AuthUserService;
import com.deng.api.service.ISysUserService;
import com.deng.api.utils.RedisUtil;
import com.deng.api.vo.UserVO;
import com.deng.commons.common.BaseResult;
import com.deng.commons.common.CodeType;
import com.deng.commons.common.ErrorCode;
import com.deng.commons.utils.CodeUtils;
import com.deng.commons.utils.UserUtils;
import com.wf.captcha.base.Captcha;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @Author by DHF
 * @Date 2022/08/2022/8/10 18:46
 * @Version 1.0
 */
@Service
@Slf4j
public class AuthUserServiceImpl implements AuthUserService {
    @Autowired
    private ISysUserService iSysUserService;
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private JWTConfig jwtConfig;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private UserDetailServiceImpl userDetailService;
    @Resource
    private RedisUtil redisUtil;

    @Override
    public BaseResult captcha() {
        Captcha captcha = CodeUtils.getCaptcha(CodeType.ARITHMETIC);
        String uuid = UUID.randomUUID().toString().replace("-","");
        redisUtil.set(uuid,captcha.text(),30);
        Map<String,Object> map = new HashMap();
        map.put("uuid",uuid);
        map.put("img",captcha.toBase64());
        return BaseResult.success(map);
    }

    @Override
    public BaseResult doLogin(UserVO userVO, HttpServletRequest request) {
        //判断验证码是否过期
        if (!redisUtil.hasKey(userVO.getUuid())){
            return BaseResult.fail(ErrorCode.CODE_10021);
        }
        if (StrUtil.isBlankIfStr(userVO.getCode()) || !redisUtil.get(userVO.getUuid()).equals(userVO.getCode())){
            return BaseResult.fail(ErrorCode.CODE_1002);
        }
        //删除redis中验证码
        redisUtil.del(userVO.getUuid());
        //通过账号查找用户
        AuthUser authUser = (AuthUser) userDetailsService.loadUserByUsername(userVO.getUsername());
        if (authUser == null ||
                !passwordEncoder.matches(userVO.getPassword(),authUser.getPassword())){
            return BaseResult.fail(ErrorCode.CODE_1003);
        }
        //登录凭证并存储SecurityContext中，
        UsernamePasswordAuthenticationToken authenticationToken
                = new UsernamePasswordAuthenticationToken(authUser,null,authUser.getAuthorities());
        authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);

        //生成token
        String token = jwtConfig.tokenHead+" "+jwtTokenUtil.generateToken(userVO.getUsername());

        //更新上次登录时间
        SysUser u = new SysUser();
        u.setId(authUser.getId());
        u.setLastLoginTime(LocalDateTime.parse(DateUtil.now(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        iSysUserService.updateById(u);

        //返回数据给前端
        Map<String,Object> map = new HashMap<>();
        map.put("token",token);
        redisUtil.set("token",token,30*60);
//        stringRedisTemplate.opsForValue().set("token",token,30,TimeUnit.MINUTES);
        map.put("user",authUser);
//        redisUtil.set("authUser",authUser!=null? authUser:"",30*60);
        stringRedisTemplate.opsForValue().set("authUser",authUser!=null? JSON.toJSONString(authUser):"",30,TimeUnit.MINUTES);
        return BaseResult.success(map);
    }

    @Override
    public BaseResult info() {
        AuthUser authUser = (AuthUser) userDetailService.loadUserByUsername(UserUtils.getUser().getUsername());
        stringRedisTemplate.opsForValue().set("authUser",authUser!=null? JSON.toJSONString(authUser):"",30,TimeUnit.MINUTES);
//        redisUtil.set("authUser",authUser!=null? authUser:"",30*60);
        return BaseResult.success(authUser);
    }
}
